package com.market.member.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.block.common.bean.CommonParam;
import com.block.common.bean.SessionBean;
import com.block.common.constant.AppRspCodeConstant;
import com.block.common.constant.RedisKeyConstant;
import com.block.common.enums.LoginStatusEnum;
import com.block.common.service.LogFactory;
import com.block.common.vo.ResponseVo;
import com.block.db.entity.MemberBaseInfo;
import com.block.db.entity.MemberLoginSession;
import com.block.db.mapper.MemberLoginSessionMapper;
import com.market.member.model.dto.LoginResultDTO;
import com.market.member.service.IMemberLoginSessionService;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 
 * @since 2023-08-05
 */
@Service
public class MemberLoginSessionServiceImpl extends ServiceImpl<MemberLoginSessionMapper, MemberLoginSession> implements IMemberLoginSessionService {

    private static final Logger log = LogFactory.getCommLog();

    @Autowired
    RedisTemplate<String, SessionBean> redisSessionTemplate;
    @Autowired
    MemberLoginSessionMapper memberLoginSessionMapper;

    @Override
    public SessionBean loginSession(LoginResultDTO loginResultDTO, CommonParam commonParam) {
        Long uid = loginResultDTO.getUid();
        MemberBaseInfo memberBaseInfo = loginResultDTO.getMemberBaseInfo();

        //查询登录状态的token
        List<MemberLoginSession> sessionList = this.baseMapper.getByUidAndStatus(uid, LoginStatusEnum.LOGIN.getValue());
        // 使之前登录的token失效
        if (!CollUtil.isEmpty(sessionList)) {
            sessionList.stream().forEach(memberLoginsession1 -> {
                String expriToken = memberLoginsession1.getToken();
                String tokenKey = RedisKeyConstant.TOKEN_REDIS_KEY_PREFIX.concat(expriToken);
                if (redisSessionTemplate.hasKey(tokenKey)) {
                    redisSessionTemplate.delete(tokenKey);
                }
                memberLoginsession1.setStatus(LoginStatusEnum.EFFECT.getValue());
                memberLoginsession1.setUpdateTime(LocalDateTime.now());
            });
            boolean result = updateBatchById(sessionList, sessionList.size());
            log.info("[批量更新token为失效状态结果]{}", result);
        }

        //登录的session不存在.则创建. 存在且未过期 则更新
        MemberLoginSession loginSession = new MemberLoginSession();
        loginSession.setDateInfo(LocalDate.now().toString());
        loginSession.setStatus(LoginStatusEnum.LOGIN.getValue());
        loginSession.setUid(uid);
        loginSession.setMobile(memberBaseInfo.getMobile());
        loginSession.setRandomUuid(commonParam.getRandomUuid());

        loginSession.setLoginType(loginResultDTO.getLoginType());
        loginSession.setReqIp(commonParam.getReqIp());

        loginSession.setLoginTime(LocalDateTime.now());
        loginSession.setUpdateTime(LocalDateTime.now());

        loginSession.setStatus(LoginStatusEnum.LOGIN.getValue());
        loginSession.setChannelCode(commonParam.getChannelCode());
        loginSession.setChannelName(commonParam.getChannelName());
        loginSession.setAppCode(commonParam.getAppCode());

        loginSession.setRegDateInfo(memberBaseInfo.getDateInfo());
        loginSession.setRegAppCode(memberBaseInfo.getRegAppCode());
        loginSession.setReqChannelCode(memberBaseInfo.getChannelCode());
        loginSession.setReqChannelName(memberBaseInfo.getChannelName());

        JSONObject headObject = commonParam.getHeadObject();
        String originparm1 = headObject.getString("originparm1");

        String extData = StrUtil.format("originparm1:{};", originparm1);
        loginSession.setExtData(extData);

        String token = UUID.fastUUID().toString(true);
        loginSession.setToken(token);
        boolean saveResult = save(loginSession);
        log.info("[集合数大于1或已经超时 保存session结果]{}", saveResult);

        String tokenKey = RedisKeyConstant.TOKEN_REDIS_KEY_PREFIX.concat(token);
        SessionBean sessionBean = new SessionBean();
        sessionBean.setToken(tokenKey);
        sessionBean.setUid(uid);

        if (memberBaseInfo != null){
            sessionBean.setUsername(memberBaseInfo.getUsername());

            sessionBean.setDateInfo(loginSession.getDateInfo());
            sessionBean.setAppCode(loginSession.getAppCode());
            sessionBean.setChannelCode(loginSession.getChannelCode());
            sessionBean.setChannelName(loginSession.getChannelName());

            sessionBean.setRegDateInfo(memberBaseInfo.getDateInfo());
            sessionBean.setRegAppCode(memberBaseInfo.getRegAppCode());
            sessionBean.setRegChannelCode(memberBaseInfo.getChannelCode());
            sessionBean.setRegChannelName(memberBaseInfo.getChannelName());

            sessionBean.setAuthFlag(memberBaseInfo.getAuthFlag());
            sessionBean.setUserType(memberBaseInfo.getType());
        }

        //存入缓存，永久有效
        redisSessionTemplate.opsForValue().set(tokenKey, sessionBean, 3l, TimeUnit.DAYS);
        return sessionBean;
    }

    @Override
    public ResponseVo logout(SessionBean sessionBean) {

        String tokenKey = RedisKeyConstant.TOKEN_REDIS_KEY_PREFIX.concat(sessionBean.getToken());
        if (redisSessionTemplate.hasKey(tokenKey)) {
            redisSessionTemplate.delete(tokenKey);
        }

        MemberLoginSession updateEntity = new MemberLoginSession();
        updateEntity.setToken(sessionBean.getToken());
        updateEntity.setStatus(LoginStatusEnum.LOGIN_OUT.getValue());
        updateEntity.setUpdateTime(LocalDateTime.now());

        this.updateById(updateEntity);
        return new ResponseVo(AppRspCodeConstant.SUCCESS);
    }

    @Override
    public ResponseVo getToken(String token) {
        Boolean result = redisSessionTemplate.hasKey(token);
        String nowDate = LocalDate.now().toString();
        Long uid = memberLoginSessionMapper.getUidByToken(token, nowDate);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("result",result);
        jsonObject.put("uid",uid);
        return new ResponseVo(AppRspCodeConstant.SUCCESS,jsonObject);
    }

    @Override
    public Long getUidByToken(String token, String nowDate) {

       return memberLoginSessionMapper.getUidByToken(token,nowDate);
    }
}
